﻿#include"stdafx.h"
#ifdef LK_FUNCTIONAL_FUNOBJ_
namespace LK
{
	namespace Functional
	{
		ptr<Object> IFunObjs::Call(ptr<Object> const&obj, ptr<Collection::IArray<ptr<Object>>>const&Arguments)const
		{
			ptr<Collection::IArray<ptr<Type>>> arr = GetArgsType();//返回值和参数类型
			if ((Arguments==null ? 0 : Arguments->size()) != arr->size() - 2)
				Throw<PFunctionalException >(L"函数调用时传入的参数数量不对,应传入" + ptr<String>(arr->size() - 2) + L"个参数，但却传入了" + ptr<String>(Arguments==null ? 0 : Arguments->size()) + L"个");
			PMObjects xr;//存放返回值的封箱
			if (!arr[0]->IsPureType() || !arr[0]->IsDerivedFrom(Type::Make<ptr<Object>>()))
				xr = MObjects::MakeMObjectByTypeInfo(arr[0]);
			ptr<Collection::IArray<void*>>args;//参数指针数组
			ptr<Collection::IArray<ptr<Object>>> xcvrt;//参数封箱数组
			if (Arguments!=null)//检测参数是否需要转换
			{
				args = new LK::Collection::DefaultArray<void*>(Arguments->size());//参数指针
				xcvrt = new LK::Collection::DefaultArray<ptr<Object>>(Arguments->size());//参数列表
				for (index_t i = 0; i < Arguments->size(); ++i)//执行必要的类型转换过程，目标是填完args数组
				{
					ptr<Type>& dt = arr[i + 2];//目标类型
					ptr<Type> st;
					if (Arguments[i]==null)
					{
						if (!dt->IsPureTypeIgnoreExtents() || dt->IsReference() || !dt->IsDerivedFrom(Type::Make<ptr<Object>>()))
							Throw<PFunctionalException >(L"传入的第" + ptr<String>(i + 1) + L"个参数为空");
					}
					else st = Arguments[i]->GetType() == Type::Make<PMObjects>() ? ((PMObjects&)Arguments[i])->GetInnerType() : Arguments[i]->GetType();
					if (st==null)
						args[i] = (void*)&Arguments[i];
					else
					{
						if (dt != st)//需要转换
							xcvrt[i] = dt->DynamicConvertFrom(Arguments[i]);
						else xcvrt[i] = Arguments[i];
						args[i] = (void*)(MObjects::GetDataPtr(xcvrt[i]));
#ifdef _CLR
						if (dt->IsGCHandle())
						{
							LK::placementnew((gcroot<System::Object^>*)&args[i], *(gcroot<System::Object^>*)args[i]);
						}
#endif
						if (dt->IsReference() || dt->IsArray() || dt->IsFunction())args[i] = *(void**)args[i];//需要从封箱数据指针转换到对象指针
					}
				}
			}
			void*pClass = MObjects::GetObjectPtr(obj );
			if (!pClass)
			{
				GetInnerPtr(&pClass);
				if (!pClass)pClass = (void*)&obj;
			}
			if (xr==null)Call(&xr, pClass, args==null ? (void**)NULL : (void**)args);
			else Call(MObjects::GetDataPtr(xr), pClass, args==null ? (void**)NULL : (void**)args);
			return xr;
		}
		void IFunObjs::AddTypeInfo()
		{
#ifdef LK_REFLECTION_
			//引用反射命名空间
			using namespace Reflection;
			//获取类库的引用
			ptr<TypeLibrary> lib = GetGlobleLibrary();
			//获取类库中的全局命名空间
			PNamespaceNode globle = lib.GetGlobleNamespaceRef();
			//添加LK命名空间
			PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
			//在LK命名空间中添加ptr<Exception>类型
			PTypeNode n = space.FindOrAddTypeNode(L"IFunObjs", Type::Make<PFunObjs>());
			//在PFunObj类型节点中添加成员函数
			//n.AddFunction(L"GetClassTypeInfo", &PFunObjs::GetClassTypeInfo);
			//n.AddFunction(L"Call", (ptr<Object>(PFunObjs::*)(ptr<Object> const&, ptr<Collection::IArray<ptr<Object>>>const&)const)&PFunObjs::Call);
			//n.AddFunction(L"GetArgsType", &PFunObjs::GetArgsType);
			//设置继承
			n.AddBaseType(Type::Make<ptr<Object>>());
#endif
		}
	}
}
#endif
